package org.light.simpleauth;

import java.util.ArrayList;
import java.util.List;

import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.exception.ValidateException;
import org.light.generator.Generator;
import org.light.utils.WriteableUtil;

public class AppTokenManagerGenerator extends Generator{
	protected Domain userDomain;

	public AppTokenManagerGenerator(Domain userDomain){
		super();
		this.setUserDomain(userDomain);
		super.fileName = "AppTokenManager.java";
	}

	public Domain getUserDomain() {
		return userDomain;
	}

	public void setUserDomain(Domain userDomain) {
		this.userDomain = userDomain;
	}

	@Override
	public StatementList generateStatementList() throws ValidateException {
		List<Writeable> sList = new ArrayList<Writeable>();
		sList.add(new Statement(1000L,0,"package "+this.userDomain.getPackageToken()+".utils;"));
        sList.add(new Statement(2000L,0,""));
        sList.add(new Statement(3000L,0,"import java.sql.Timestamp;"));
        sList.add(new Statement(4000L,0,"import java.util.Map;"));
        sList.add(new Statement(5000L,0,"import java.util.TreeMap;"));
        sList.add(new Statement(6000L,0,""));
        sList.add(new Statement(7000L,0,"public class AppTokenManager {"));
        sList.add(new Statement(8000L,1,"protected static Map<String, LoginRecord> loginUsers = new TreeMap<>();"));
        sList.add(new Statement(9000L,0,""));
        sList.add(new Statement(10000L,1,"public static String loginUser(String userName){"));
        sList.add(new Statement(11000L,2,"String token = generateRandomToken();"));
        sList.add(new Statement(13000L,2,"Timestamp loginTime = new Timestamp(System.currentTimeMillis());"));
        sList.add(new Statement(14000L,2,"LoginRecord lr = new LoginRecord();"));
        sList.add(new Statement(15000L,2,"lr.setLoginTime(loginTime);"));
        sList.add(new Statement(16000L,2,"lr.setUserName(userName);"));
        sList.add(new Statement(17000L,2,"loginUsers.put(token,lr);"));
        sList.add(new Statement(18000L,2,"return token;"));
        sList.add(new Statement(19000L,1,"}"));
        sList.add(new Statement(20000L,0,""));
        sList.add(new Statement(21000L,1,"public static void logoutUser(String token){"));
        sList.add(new Statement(22000L,2,"loginUsers.remove(token);"));
        sList.add(new Statement(23000L,1,"}"));
        sList.add(new Statement(24000L,0,""));
        sList.add(new Statement(25000L,1,"public static void logoutUserViaUserName(String userName){"));
        sList.add(new Statement(26000L,2,"for (String token:loginUsers.keySet()){"));
        sList.add(new Statement(27000L,3,"LoginRecord lr = loginUsers.get(token);"));
        sList.add(new Statement(28000L,3,"String userName0 = lr.getUserName();"));
        sList.add(new Statement(29000L,3,"if (userName0.equals(userName)){"));
        sList.add(new Statement(30000L,4,"loginUsers.remove(token);"));
        sList.add(new Statement(31000L,3,"}"));
        sList.add(new Statement(32000L,2,"}"));
        sList.add(new Statement(33000L,1,"}"));
        sList.add(new Statement(34000L,0,""));
        sList.add(new Statement(35000L,1,"public static String getUserNameViaToken(String token){"));
        sList.add(new Statement(36000L,2,"LoginRecord lr = loginUsers.get(token);"));
        sList.add(new Statement(37000L,2,"if (lr != null){"));
        sList.add(new Statement(38000L,3,"if (!isTimeOut(lr.getLoginTime())) {"));
        sList.add(new Statement(39000L,4,"Timestamp now =  new Timestamp(System.currentTimeMillis());"));
        sList.add(new Statement(40000L,4,"lr.setLoginTime(now);"));
        sList.add(new Statement(41000L,4,"return lr.getUserName();"));
        sList.add(new Statement(42000L,3,"} else {"));
        sList.add(new Statement(43000L,4,"loginUsers.remove(token);"));
        sList.add(new Statement(44000L,3,"}"));
        sList.add(new Statement(45000L,2,"}"));
        sList.add(new Statement(46000L,2,"return null;"));
        sList.add(new Statement(47000L,1,"}"));
        sList.add(new Statement(48000L,0,""));
        sList.add(new Statement(49000L,1,"public static boolean isTimeOut(Timestamp timestamp){"));
        sList.add(new Statement(50000L,2,"Timestamp now = new Timestamp(System.currentTimeMillis());"));
        sList.add(new Statement(51000L,2,"int diff = now.compareTo(timestamp);"));
        sList.add(new Statement(52000L,2,"if (diff > 1000*60*10) return true;"));
        sList.add(new Statement(53000L,2,"else return false;"));
        sList.add(new Statement(54000L,1,"}"));
        sList.add(new Statement(55000L,0,""));
        sList.add(new Statement(56000L,2,""));
        sList.add(new Statement(57000L,1,"public  static String generateRandomToken(){"));
        sList.add(new Statement(58000L,2,"String token = generatePureRandomToken();"));
        sList.add(new Statement(59000L,2,"while (!uniqueToken(token)){"));
        sList.add(new Statement(60000L,3,"token = generatePureRandomToken();"));
        sList.add(new Statement(61000L,2,"}"));
        sList.add(new Statement(62000L,2,"return token;"));
        sList.add(new Statement(63000L,1,"}"));
        sList.add(new Statement(64000L,1,""));
        sList.add(new Statement(65000L,1,"public  static String generatePureRandomToken(){"));
        sList.add(new Statement(66000L,2,"StringBuilder tokenBuilder = new StringBuilder();"));
        sList.add(new Statement(67000L,2,"char [] pinletters = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};"));
        sList.add(new Statement(68000L,2,"for(int i=0;i<40;i++)"));
        sList.add(new Statement(69000L,2,"{"));
        sList.add(new Statement(70000L,3,"tokenBuilder.append(pinletters[(int)(Math.random()*16)]);"));
        sList.add(new Statement(71000L,2,"}"));
        sList.add(new Statement(72000L,2,"return tokenBuilder.toString();"));
        sList.add(new Statement(73000L,1,"}"));
        sList.add(new Statement(74000L,1,""));
        sList.add(new Statement(75000L,1,"public static boolean uniqueToken(String token){"));
        sList.add(new Statement(76000L,2,"for (String key :loginUsers.keySet()){"));
        sList.add(new Statement(77000L,3,"if (key.equals(token)) return false;"));
        sList.add(new Statement(78000L,2,"}"));
        sList.add(new Statement(79000L,2,"return true;"));
        sList.add(new Statement(80000L,1,"}"));
        sList.add(new Statement(81000L,0,"}"));
        sList.add(new Statement(82000L,0,""));
        sList.add(new Statement(83000L,0,"class LoginRecord implements Comparable<LoginRecord>{"));
        sList.add(new Statement(84000L,1,"protected String userName;"));
        sList.add(new Statement(85000L,1,"protected Timestamp loginTime;"));
        sList.add(new Statement(86000L,0,""));
        sList.add(new Statement(87000L,1,"public String getUserName() {"));
        sList.add(new Statement(88000L,2,"return userName;"));
        sList.add(new Statement(89000L,1,"}"));
        sList.add(new Statement(90000L,1,"public void setUserName(String userName) {"));
        sList.add(new Statement(91000L,2,"this.userName = userName;"));
        sList.add(new Statement(92000L,1,"}"));
        sList.add(new Statement(93000L,1,"public Timestamp getLoginTime() {"));
        sList.add(new Statement(94000L,2,"return loginTime;"));
        sList.add(new Statement(95000L,1,"}"));
        sList.add(new Statement(96000L,1,"public void setLoginTime(Timestamp loginTime) {"));
        sList.add(new Statement(97000L,2,"this.loginTime = loginTime;"));
        sList.add(new Statement(98000L,1,"}"));
        sList.add(new Statement(99000L,1,"@Override"));
        sList.add(new Statement(100000L,1,"public int compareTo(LoginRecord o) {"));
        sList.add(new Statement(101000L,2,"return this.userName.compareTo(o.getUserName());"));
        sList.add(new Statement(102000L,1,"}"));
        sList.add(new Statement(103000L,0,"}"));
		return WriteableUtil.merge(sList);
	}
}
